// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import Over from "./Over";

const { ccclass, property } = cc._decorator;

@ccclass
export default class GameScene extends cc.Component {

    @property(cc.Node)
    nodePlayer: cc.Node = null;

    @property({ type: cc.SpriteFrame })
    sfPlayer: cc.SpriteFrame = null;

    @property(cc.Label)
    labelScore: cc.Label = null;

    @property(cc.ProgressBar)
    progressBar: cc.ProgressBar = null;

    @property(cc.Prefab)
    prefabStar: cc.Prefab = null;

    @property(cc.Prefab)
    prefabOver: cc.Prefab = null;

    _minY: number = 0;

    _starPool: cc.NodePool = null;

    _score: number = 0;

    _over: boolean = false;

    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        //获取碰撞检测系统
        let manager = cc.director.getCollisionManager();
        //默认碰撞检测系统是禁用的，如果需要使用则需要以下方法开启碰撞检测系统
        manager.enabled = true;
        //默认碰撞检测系统的 debug 绘制是禁用的，如果需要使用则需要以下方法开启 debug 绘制：
        // manager.enabledDebugDraw = true;
        //如果还希望显示碰撞组件的包围盒，那么可以通过以下接口来进行设置：
        // manager.enabledDrawBoundingBox = true;

        //初始化对象池
        this._starPool = new cc.NodePool();
        let initCount = 5;
        for (let i = 0; i < initCount; ++i) {
            let node = cc.instantiate(this.prefabStar); // 创建节点
            this._starPool.put(node); // 通过 put 接口放入对象池
        }
    }

    start() {
        //注册触摸事件
        // this.node.on("touchend", this.onTouchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);

        //获得怪物在地面的位置
        this._minY = this.nodePlayer.y;

        this.resetProgress();

        this.createStar();
    }

    // update (dt) {}

    onTouchEnd(event: cc.Event.EventTouch) {
        if (this._over) {
            return;
        }
        
        //获取触摸点坐标(左下角为原点)
        let location = event.getLocation();
        // console.log("location: " + location.toString());
        //转换成当前节点坐标(中心点为原点)
        location = this.node.convertToNodeSpaceAR(location);
        // console.log("node location: " + location.toString());

        //判断触摸位置在怪物下面，则不进行跳跃
        if (location.y < this.nodePlayer.y) {
            return;
        }

        //停止之前的所有运动
        cc.Tween.stopAllByTarget(this.nodePlayer);

        //跳跃高度
        let height = location.y - this.nodePlayer.y;
        //跳跃动作
        let jump = cc.jumpTo(1, cc.v2(location.x, this._minY), height, 1);
        //执行动作
        cc.tween(this.nodePlayer).then(jump).start();
    }

    resetProgress() {
        cc.Tween.stopAllByTarget(this.progressBar);
        this.progressBar.progress = 1;
        cc.tween(this.progressBar).to(5, { progress: 0 }).call(this.over.bind(this)).start();
    }

    catchStar(node: cc.Node) {
        this._starPool.put(node); // 和初始化时的方法一样，将节点放进对象池，这个方法会同时调用节点的 removeFromParent

        this.resetProgress();

        this.createStar();

        this.labelScore.string = String(++this._score);
    }

    createStar() {
        let node = null;
        if (this._starPool.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
            node = this._starPool.get();
        } else { // 如果没有空闲对象，也就是对象池中备用对象不够时，我们就用 cc.instantiate 重新创建
            node = cc.instantiate(this.prefabStar);
        }
        node.parent = this.node; // 将生成的敌人加入节点树

        let maxX = cc.winSize.width / 2 - node.width / 2;
        let minX = -maxX;
        node.x = this.random(minX, maxX);

        let maxY = cc.winSize.height / 2 - node.width / 2;
        let minY = this._minY;
        node.y = this.random(minY, maxY);
    }

    random(min: number, max: number) {
        return Math.random() * (max - min + 1) + min;
    }

    over() {
        this._over = true;

        //销毁分数
        this.labelScore.node.parent.destroy();
        //更换怪物图片
        this.nodePlayer.getComponent(cc.Sprite).spriteFrame = this.sfPlayer;

        //计时器 0.8秒后弹出结算页面
        this.scheduleOnce(() => {
            let node = cc.instantiate(this.prefabOver);
            node.zIndex = cc.macro.MAX_ZINDEX;
            node.parent = this.node;
            node.getComponent(Over).init(this._score);
        }, 0.8);
    }
}
